﻿using System;
using System.Collections.Generic;
using System.Linq;
using Autodesk.Revit.DB;
using YArchitech.Revit;

namespace HYFloorPipeModule
{
	public class YxPipesEdge
	{
		public YxPipesEdge(List<XYZ> points, DrawYxFloorPipeData dyfpd)
		{
			this.allPoints = (points ?? null);
			this.drawYxFloorPipeData = dyfpd;
		}

		public void SetIn(bool bIn)
		{
			this.isIn = bIn;
		}

		public void CreatBound(List<MixPair> boundingMixPairs = null)
		{
			if (this.lstMixPair == null)
			{
				this.lstMixPair = new List<MixPair>();
			}
			if (boundingMixPairs != null)
			{
				this.lstMixPair.AddRange(from bouding in boundingMixPairs
				select bouding);
			}
			else
			{
				for (int i = 0; i < this.allPoints.Count; i++)
				{
					if (i == this.allPoints.Count - 1)
					{
						MixPair item = new MixPair(this.allPoints[i], this.allPoints[0], this.isIn);
						this.lstMixPair.Add(item);
					}
					else
					{
						MixPair item2 = new MixPair(this.allPoints[i], this.allPoints[i + 1], this.isIn);
						this.lstMixPair.Add(item2);
					}
				}
			}
			this.GetCrossDirection();
		}

		private void GetCrossDirection()
		{
			this.vecCross = new XYZ(0.0, 0.0, 1.0);
			XYZ xyz = this.vecCross.CrossProduct(this.lstMixPair[0].AsVector());
			XYZ pt = 0.5 * (this.lstMixPair[0].Start + this.lstMixPair[0].End) + xyz * 1.0 / 304.8;
			if (this.allPoints == null)
			{
				this.allPoints = new List<XYZ>();
				this.allPoints.AddRange(from mixPair in this.lstMixPair
				select mixPair.Start);
			}
			if (!YJKRevitTools.Contains(pt, this.allPoints))
			{
				this.vecCross = -this.vecCross;
			}
		}

		public void Offset(double dOffset)
		{
			this.lstMPs = new List<MixPair>();
			for (int i = 0; i < this.lstMixPair.Count; i++)
			{
				double dFirst = 0.0;
				double dEnd = 0.0;
				if (this.lstMixPair.Count >= 3)
				{
					bool flag;
					if (i == 0)
					{
						flag = this.CanDraw(this.lstMixPair[this.lstMixPair.Count - 1], this.lstMixPair[i], this.lstMixPair[i + 1], dOffset, out dFirst, out dEnd);
					}
					else if (i == this.lstMixPair.Count - 1)
					{
						flag = this.CanDraw(this.lstMixPair[i - 1], this.lstMixPair[i], this.lstMixPair[0], dOffset, out dFirst, out dEnd);
					}
					else
					{
						flag = this.CanDraw(this.lstMixPair[i - 1], this.lstMixPair[i], this.lstMixPair[i + 1], dOffset, out dFirst, out dEnd);
					}
					if (flag)
					{
						XYZ xyz = this.vecCross.CrossProduct(this.lstMixPair[i].AsVector());
						if (i == 0 && this.bFirst)
						{
							this.firstDir = xyz;
							this.bFirst = false;
						}
						this.lstMixPair[i].Offset(xyz * dOffset);
						this.lstMixPair[i].Retract(dFirst, dEnd);
						this.lstMixPair[i].IsIn = this.isIn;
						this.lstMPs.Add(new MixPair(this.lstMixPair[i]));
					}
					else
					{
						this.lstMixPair.Remove(this.lstMixPair[i]);
						i--;
					}
				}
			}
			this.AddToList(this.lstMPs);
		}

		public void Offsetnew(double dOffset)
		{
			for (int i = 0; i < this.lstMixPair.Count; i++)
			{
				XYZ xyz = this.vecCross.CrossProduct(this.lstMixPair[i].AsVector());
				if (i == 0 && this.bFirst)
				{
					this.firstDir = xyz;
					this.bFirst = false;
				}
				this.lstMixPair[i].Offset(xyz * dOffset);
				this.lstMixPair[i].IsIn = this.isIn;
			}
			bool flag = this.BoundingsHasParallel();
			int num = 0;
			while (num < this.lstMixPair.Count && this.lstMixPair.Count >= 3)
			{
				if (!flag)
				{
					goto IL_199;
				}
				int j = num;
				XYZ xyz2 = this.lstMixPair[num].AsVector();
				for (int k = num + 1; k < this.lstMixPair.Count; k++)
				{
					XYZ xyz3 = this.lstMixPair[k].AsVector();
					if (xyz2.IsAlmostEqualTo(-xyz3) && this.lstMixPair[num].DistanceTo(this.lstMixPair[k]) <= dOffset + 0.016404199475065617)
					{
						j = k;
						break;
					}
				}
				if (j == num)
				{
					goto IL_199;
				}
				for (j--; j > num; j--)
				{
					this.lstMixPair.RemoveAt(j);
				}
				if (this.lstMixPair[num].GetLength() > this.lstMixPair[j + 1].GetLength())
				{
					this.lstMixPair.RemoveAt(j + 1);
				}
				else
				{
					this.lstMixPair.RemoveAt(num);
				}
				num--;
				IL_286:
				num++;
				continue;
				IL_199:
				XYZ vec = this.vecCross.CrossProduct(this.lstMixPair[num].AsVector());
				bool flag2;
				if (num == 0)
				{
					flag2 = this.TrimBounding(this.lstMixPair[this.lstMixPair.Count - 1], this.lstMixPair[num], this.lstMixPair[num + 1], vec, dOffset);
				}
				else if (num == this.lstMixPair.Count - 1)
				{
					flag2 = this.TrimBounding(this.lstMixPair[num - 1], this.lstMixPair[num], this.lstMixPair[0], vec, dOffset);
				}
				else
				{
					flag2 = this.TrimBounding(this.lstMixPair[num - 1], this.lstMixPair[num], this.lstMixPair[num + 1], vec, dOffset);
				}
				if (flag2)
				{
					this.lstMixPair.RemoveAt(num);
					num--;
					goto IL_286;
				}
				goto IL_286;
			}
			if (this.lstMixPair.Count >= 3)
			{
				using (List<MixPair>.Enumerator enumerator = this.lstMixPair.GetEnumerator())
				{
					while (enumerator.MoveNext())
					{
						if (enumerator.Current.GetLength() < 0.032808398950131233)
						{
							this.lstMixPair.Clear();
							break;
						}
					}
				}
				for (int l = 0; l < this.lstMixPair.Count - 2; l++)
				{
					for (int m = l + 2; m < this.lstMixPair.Count - 1; m++)
					{
						if (this.lstMixPair[l].HasIntersectionTo(this.lstMixPair[m]))
						{
							this.lstMixPair.Clear();
							break;
						}
					}
				}
				int num2 = 0;
				while (num2 < this.lstMixPair.Count && this.preLoopMp != null)
				{
					for (int n = 0; n < this.preLoopMp.Count; n++)
					{
						if (this.lstMixPair[num2].HasIntersectionTo(this.preLoopMp[n]))
						{
							this.lstMixPair.Clear();
							break;
						}
					}
					num2++;
				}
			}
			this.AddToList(this.lstMixPair);
		}

		private bool TrimBounding(MixPair befMp, MixPair curMp, MixPair nexMp, XYZ vec, double dDis)
		{
			if (curMp.CreateCurve().Length < dDis)
			{
				return true;
			}
			bool flag = false;
			XYZ intersectionPoint = this.GetIntersectionPoint(befMp.CreateCurve(), curMp.CreateCurve());
			XYZ intersectionPoint2 = this.GetIntersectionPoint(curMp.CreateCurve(), nexMp.CreateCurve());
			if (intersectionPoint == null || intersectionPoint2 == null)
			{
				return true;
			}
			if ((intersectionPoint2 - intersectionPoint).Normalize().IsAlmostEqualTo(-curMp.AsVector()))
			{
				return true;
			}
			if (intersectionPoint.DistanceTo(intersectionPoint2) < 1.01 * dDis)
			{
				XYZ intersectionPoint3 = this.GetIntersectionPoint(befMp.CreateCurve(), nexMp.CreateCurve());
				if (intersectionPoint3 == null)
				{
					if (intersectionPoint.DistanceTo(intersectionPoint2) < dDis)
					{
						flag = true;
					}
				}
				else
				{
					XYZ xyz = (intersectionPoint3 - curMp.CreateCurve().Project(intersectionPoint3).XYZPoint).Normalize();
					if (vec.IsAlmostEqualTo(xyz))
					{
						flag = true;
					}
				}
			}
			if (!flag)
			{
				curMp.Start = intersectionPoint;
				curMp.End = intersectionPoint2;
			}
			return flag;
		}

		private XYZ GetIntersectionPoint(Curve c1, Curve c2)
		{
			List<XYZ> list = new List<XYZ>();
			XYZ endPoint = c1.GetEndPoint(1);
			XYZ endPoint2 = c2.GetEndPoint(0);
			if (c1.IsBound)
			{
				c1.MakeUnbound();
			}
			if (c2.IsBound)
			{
				c2.MakeUnbound();
			}
			IntersectionResultArray intersectionResultArray = new IntersectionResultArray();
			SetComparisonResult setComparisonResult = c1.Intersect(c2, out intersectionResultArray);
			if (4 != (int)setComparisonResult && intersectionResultArray != null && !intersectionResultArray.IsEmpty)
			{
				for (int i = 0; i < intersectionResultArray.Size; i++)
				{
					list.Add(intersectionResultArray.get_Item(i).XYZPoint);
				}
			}
			if (list.Count == 0)
			{
				return null;
			}
			double num = list[0].DistanceTo(endPoint) + list[0].DistanceTo(endPoint2);
			XYZ result = list[0];
			foreach (XYZ xyz in list)
			{
				if (num > xyz.DistanceTo(endPoint) + xyz.DistanceTo(endPoint2))
				{
					num = xyz.DistanceTo(endPoint) + xyz.DistanceTo(endPoint2);
					result = xyz;
				}
			}
			return result;
		}

		private bool BoundingsHasParallel()
		{
			for (int i = 0; i < this.lstMixPair.Count - 1; i++)
			{
				for (int j = i + 1; j < this.lstMixPair.Count; j++)
				{
					if (this.lstMixPair[i].IsParallel(this.lstMixPair[j]))
					{
						return true;
					}
				}
			}
			return false;
		}

		private bool CanDraw(MixPair befMP, MixPair curMP, MixPair nexMp, double dOffset, out double befOffset, out double nexOffset)
		{
			double twoVectorAngle = YJKRevitTools.GetTwoVectorAngle(-befMP.AsVector(), curMP.AsVector(), new XYZ(0.0, 0.0, 1.0));
			double twoVectorAngle2 = YJKRevitTools.GetTwoVectorAngle(-curMP.AsVector(), nexMp.AsVector(), new XYZ(0.0, 0.0, 1.0));
			befOffset = dOffset * Math.Tan((Math.PI - twoVectorAngle) * 0.5);
			nexOffset = dOffset * Math.Tan((Math.PI - twoVectorAngle2) * 0.5);
			return curMP.GetLength() > befOffset + nexOffset;
		}

		public bool CanContinueDraw()
		{
			return this.lstMixPair.Count > 2;
		}

		private void AddToList(List<MixPair> lst)
		{
			this.allMp = (this.allMp ?? new List<MixPair>());
			this.preLoopMp = (this.preLoopMp ?? new List<MixPair>());
			this.preLoopMp.Clear();
			for (int i = 0; i < lst.Count; i++)
			{
				this.allMp.Add(new MixPair(lst[i]));
				this.preLoopMp.Add(new MixPair(lst[i]));
			}
		}

		private DrawYxFloorPipeData drawYxFloorPipeData;

		private bool isIn;

		private List<XYZ> allPoints;

		public List<PointPair> lstPointPairsAll;

		public List<MixPair> lstMixPair;

		private List<MixPair> lstMPs;

		private List<MixPair> preLoopMp;

		private XYZ vecCross;

		public List<MixPair> allMp;

		public List<Curve> lstCurvesIn;

		public List<Curve> lstCurvesOut;

		public XYZ firstDir;

		private bool bFirst = true;
	}
}
